import datetime
import os
import math
import Core.Config as Config
import Core.WindFunctions as Wind


class Download_DailyQuote(object):

    def __init__(self, database, wind_object):
        self.database = database
        self.wind_object = wind_object
        self.instrument_type = "unknown"
        self.fields = "open,high,low,close,volume,amt"
        self.field_map = {}

    def download_data(self, symbol, datetime1, datetime2, save=False):
        # ---把 map 全部变成大写, Wind 返回的 Fields 都是大写
        for key in list(self.field_map.keys()):
            value = self.field_map.get(key)
            self.field_map[key.upper()] = value

        #
        document_list = []

        # ---Request Functions---
        param = ""
        data = self.wind_object.wsd(symbol, self.fields, datetime1, datetime2, param)

        #
        if data.ErrorCode != 0:
            raise Exception("Download_DailyQuote::download_data, No Data: " + symbol)
            return

        # ---转存到document---
        for i_day in range(len(data.Times)):  # 循环每一天

            # 虽然返回了数据，但是数据为空 # 如果第一个字段的数据（往往是最重要的）都是空的话，大概率是缺失数据
            if data.Data[0][i_day] == None:
                continue

            dataObject = {}
            dataObject["Symbol"] = symbol
            # dataObject["DateTime"] = data.Times[i_day]  # 20210603 为了减轻数据库负担，不再支持时间戳
            dataObject["Date"] = data.Times[i_day]
            dataObject["Key2"] = symbol + "_" + dataObject["Date"].strftime('%Y-%m-%d')

            for i_field in range(len(data.Fields)):
                wind_field = data.Fields[i_field]
                database_filed = self.field_map.get(wind_field)
                if database_filed != None:
                    dataObject[database_filed] = data.Data[i_field][i_day]
                else:
                    raise Exception("Download_DailyQuote::download_data, Missing wind_field map to database_field: " + wind_field)

            # 检查数据
            # ---Invalid Data---
            if "Close" in dataObject and (dataObject["Close"] == None or math.isnan(dataObject["Close"])):
                continue

            # 缺失数据补空 20210603 不确定是否应该启用
            # for k, v in dataObject.items():
            #     if not isinstance(v, float):
            #         continue
            #     if math.isnan(v):
            #         dataObject[k] = None

            # 可能需要额外处理
            self.process_document(dataObject)
            #
            document_list.append(dataObject)
        #
        if save:
            self.save_data(document_list)
        #
        return document_list

    # 额外处理数据
    def process_document(self, document):
        pass

    def save_data(self, document_list):
        instrument_type = self.instrument_type
        time2 = datetime.datetime.now()
        # Save Data
        self.database.Upsert_Many("financial_data", instrument_type + "_dailybar", {}, document_list)
        time3 = datetime.datetime.now()
        print("Save to DataBase Time:  " + str((time3 - time2).total_seconds()), "#Elements", len(document_list))


class Downloag_Stock_DailyQuote(Download_DailyQuote):

    def __init__(self, database, wind_object):
        self.wind_object = wind_object
        self.instrument_type = "stock"
        #
        self.fields = self.fields + ",adjfactor,dealnum,turn,free_turn,trade_status,total_shares,free_float_shares"
        #
        self.field_map = {}

    # 股票的额外处理，处理复权问题
    def process_document(self, document):
        document["BOpen"] = document["Open"] * document["AdjFactor"]
        document["BHigh"] = document["High"] * document["AdjFactor"]
        document["BLow"] = document["Low"] * document["AdjFactor"]
        document["BClose"] = document["Close"] * document["AdjFactor"]


class Downloag_MutualFund_DailyQuote(Download_DailyQuote):

    def __init__(self, database, wind_object):
        self.database = database
        self.wind_object = wind_object
        self.instrument_type = "mutualfund"
        #
        self.fields = "NAV,NAV_ADJ,NAV_ACC"  # 单位净值; 复权单位净值; 累计单位净值, NAV_date
        #
        self.field_map = {}
        self.field_map["NAV"] = "net_asset_value"
        self.field_map["NAV_ADJ"] = "Adjusted_Net_Asset_Value"
        self.field_map["NAV_ACC"] = "Accumulated_Net_Asset_Value"

    def process_document(self, document):
        # 不确定是否应该保留
        # if instrumentType == "MutualFund":
        #     if dataObject["NAV_date"].date() < dataObject["DateTime"].date():
        #         continue
        #     del dataObject["NAV_date"]
        pass


if __name__ == '__main__':

    # ---Connecting Database---
    path_filename = os.getcwd() + "\..\Config\config_local.json"
    database = Config.create_database(database_type="MySQL", config_file=path_filename, config_field="MySQL")

    # ---Start Wind API---
    Wind.w.start()

    #
    downloader = Downloag_MutualFund_DailyQuote(database, Wind.w)
    #
    datetime1 = datetime.datetime(2021, 5, 29)
    datetime2 = datetime.datetime(2021, 5, 30)
    symbol = "000001.OF"
    downloader.download_data(symbol, datetime1, datetime2, save=True)